var objSites = new Object();
var objSitesTemplate;
var requestTimeout = 1000 * 10;  // 10 секунд

function upgrade() {
  var confText = "Расширение UNITTCEX обновилось.\n\n"
  confText += "Для завершения процесса необходимо проверить текущую конфигурацию и добавить в неё новые параметры.";
  confText += "\n\n";
  confText += "Выполнить?\n";

  if (! confirm(confText))
    return;

  console.log("Запуск процедуры обновления конфигурации");
  //она здесь когда-нибудь будет, я надеюсь.
}

//Функция заполнения тэга <select>
function populateSelect (node, obj) {
 for (i = 0; i < obj.host.length; i++) {
    node.innerHTML += "<option value='"+i+"'>"+obj.host[i].name+"</option>";
  } 
}

//Запускаем в самом начале
function init() {
  
  //Загружаем шаблоны
  var rawSitesData = document.getElementById("template").innerHTML;
  //Перевод XML в объект
  objSitesTemplate = xml2json.parser(rawSitesData,"template");
  objSitesTemplate.host.sort(sortByName);
  //Загружаем настройки из локального хранилища
  objSites.host = JSON.parse(localStorage["objSites.host"]);

  document.getElementById("selSitesTemplate").innerHTML = "<option value='-1'>Список доступных трекеров</option>";
  document.getElementById("advancedMode").checked = false;
  advancedMode_toggle();

  populateSelect(document.getElementById("selSitesTemplate"), objSitesTemplate);

  restore_options();
}

//Заполнить поля
function restore_options() {
  document.getElementById("selSites").innerHTML = "";
  if (objSites.host) {
    objSites.host.sort(sortByName);
    populateSelect(document.getElementById("selSites"), objSites);
  }
  document.getElementById("xmltext").value = "";

  document.getElementById("detect").disabled = true;
  document.getElementById("resethost").disabled = true;
}

//Перевод из XML в текст
function dumpHost (hObj) {
  var res;
  res =  "<host>\n";
  res += "  <name>"+hObj.name+"</name>\n";
  if (hObj.href)
  res += "  <href>"+hObj.href+"</href>\n";
  for (i = 0; i < hObj.parm.length; i++) {
  res += "  <parm name=\""+hObj.parm[i].name+"\">\n";
    if (hObj.parm[i].txt)
  res += "    <txt>"+hObj.parm[i].txt+"</txt>\n";
    if (hObj.parm[i].url)
  res += "    <url>"+hObj.parm[i].url+"</url>\n";
    if (hObj.parm[i].regexp) 
  res += "    <regexp>"+hObj.parm[i].regexp+"</regexp>\n";

    if (hObj.parm[i].detect) {
  res += "    <detect auto=\""+hObj.parm[i].detect.auto+"\">\n";
  if (hObj.parm[i].detect.url)
  res += "      <url>"+hObj.parm[i].detect.url+"</url>\n";
  if (hObj.parm[i].detect.regexp) {
  var t = toArray(hObj.parm[i].detect.regexp);
  for (j = 0; j < t.length; j++)
  res += "      <regexp>"+t[j]+"</regexp>\n";
  }
  if (hObj.parm[i].detect.relative)
  res += "      <relative>"+hObj.parm[i].detect.relative+"</relative>\n";
  if (hObj.parm[i].detect.baseurl)
  res += "      <baseurl>"+hObj.parm[i].detect.baseurl+"</baseurl>\n";
  res += "    </detect>\n";
  if (hObj.parm[i].href)
  res += "    <href>"+hObj.parm[i].href+"</href>\n";
  if (hObj.parm[i].skip)
  res += "    <skip>"+hObj.parm[i].skip+"</skip>\n";
  if (hObj.parm[i].zero != null)
  res += "    <zero>"+hObj.parm[i].zero+"</zero>\n";
  }
  
  res += "  </parm>\n";
  }
  
  if (hObj.check)
  res += "  <check>"+hObj.check+"</check>\n";
  res += "<host>";

  return res;
}

//Вызывается при изменении selSites
function on_selSites_change () {
  //Индекс
  var i = document.getElementById("selSites").value;
  if (i) {
    document.getElementById("xmltext").value = dumpHost(objSites.host[i]);
    document.getElementById("detect").disabled = true;
    document.getElementById("resethost").disabled = false;
    for (j = 0; j < objSites.host[i].parm.length; j++)
      if (objSites.host[i].parm[j].detect.auto == "true")
	document.getElementById("detect").disabled = false;
  } else {
    document.getElementById("detect").disabled = true;
    document.getElementById("resethost").disabled = true;
    document.getElementById("xmltext").value = "";
  }
}

function on_selSites_dblclick() {
  var i = document.getElementById("selSites").value;
  if (i) {
    objSites.host.splice(i,1);
    document.getElementById("selSites").innerHTML = "";
    document.getElementById("selSites").value = "";
    populateSelect(document.getElementById("selSites"), objSites);
    on_selSites_change ();
  }
}

function on_selSitesTemplate_change () {
  var i = document.getElementById("selSitesTemplate").value;
  var s = findHostIndexByName(objSitesTemplate.host[i].name, objSites);
  var needAutoDetect = true;
  if (i >= 0) {
    if (s != null && s >= 0) {
      document.getElementById("selSites").value = s;
      needAutoDetect = false;
    } else {
      var j = objSites.host.push(objSitesTemplate.host[i]) - 1;
      document.getElementById("selSites").innerHTML = "";
      populateSelect(document.getElementById("selSites"), objSites);
      document.getElementById("selSites").value = j;
      document.getElementById("xmltext").value = dumpHost(objSites.host[j]);
    }
    document.getElementById("selSitesTemplate").value = -1;
    on_selSites_change ();
    if (needAutoDetect && !document.getElementById("detect").disabled)
      autodetect_host();
  }
}

function on_xmltext_change() {
  var i = document.getElementById("selSites").value;
  var t = xml2json.parser(document.getElementById("xmltext").value, "host");
  if (t)
    objSites.host[i] = t;
}

function autodetect_host() {
  set_inactive_all();
  autodetect();
  //set_active_default();
  //on_selSites_change();
}

//Функция автоопределения параметров
function autodetect () {
  var xhr = new XMLHttpRequest();
  //Индекс выделенного трекера
  var c = document.getElementById("selSites").value;
  //Трекер в виде объекта
  var hObj = objSites.host[c];
  //Индекс для массива hObj.parm[]
  var i = -1;
  //Внутренний объект
  var iObj;
  //УРЛ запроса
  var tURL;
  //флаг завершения обработки запроса
  var finished = true;
  //Пауза
  var sleep_timeout = 1000;
  var short_sleep = 100;
  var aSleep;

  //Функция отмены слишком долгих запросов
    var abortTimerId;
    function setTimeoutHandler(aTimeout) {
      abortTimerId = window.setTimeout(function() {
	  xhr.abort();
	  console.log("Во время обработки "+hObj.name+" "+iObj.name+" возникли проблемы с Интернетом. Я, пожалуй, оставлю старые данные.");
	  finished = true;
      }, aTimeout);
    }

    function clearTimeoutHandler() {
      window.clearTimeout(abortTimerId);
    }

  //Внутрення функция, отвечающая непосредственно за обработку ответа
  function local_getInfo(){
    var regexpArray = new Array();
    //console.log(hObj.name+" xhr.readyState="+xhr.readyState);
    //Если мы таки что-то получили
    if (xhr.readyState == 4 && xhr.status == 200) {
      //Подготовка к парсингу
      var t1 = xhr.responseText;
      var t2 = "";
      if (xhr.responseText) {
      	regexpArray = toArray(iObj.regexp);
	//Применить все регекспы последовательно, при чём каждый следующий - к результату предыдущего
	for (var n = 0; n < regexpArray.length; n++) {
	  var tr = unescape(regexpArray[n]);
	  var r = new RegExp(tr, "igm");
	  t2 = r.exec(t1);
	  t1=t2
	}
	//Мы что-то нашли!
	if (t1) {
	  res = t1[t1.length-1]
	  console.log(hObj.name+" autodetection result="+res);
	  var burl = hObj.href;
	  if (iObj.relative == "true")
	    burl = iObj.baseurl
	  hObj.parm[i].url = burl + url_xml_esc(res);
	  //document.getElementById("xmltext").value = dumpHost(hObj);
	  if (document.getElementById("advancedMode").checked)
	    document.getElementById("verify_options").innerHTML += hObj.name+" "+hObj.parm[i].name+" autodetection result="+unescape(hObj.parm[i].url)+"<br />";
	  document.getElementById("verify_options").innerHTML += "Автоопределение успешно заверешено.<br />";
	  document.getElementById("verify_options").innerHTML += "Чтобы убедиться, что всё действительно в порядке, нажмите, пожалуйста, кнопку <b>Проверить конфигурацию</b><br />";
	} else {
	  console.log("Автоопределение ничего не нашло.");
	  document.getElementById("verify_options").innerHTML = "Автоопределение не удалось. Возможно, не выполнен вход на трекер.";
	}
      } else {
	console.log("Не получил ответа. Проверьте url: " + tURL);
      }
    //Когда запрос завершён, установить соотв. флаг
    finished = true;
    }

    //if (xhr.readyState == 4) finished = true;
  }

  //Функция запускается с паузой, т.к. в Яваскрипте до сих пор нет sleep()
  function local_sleep() {
    try {
      //Если запрос не завершён, ждём ещё
      if (!finished) {
	window.setTimeout(local_sleep, aSleep);
	return;
      }

      //Если мы попали сюда, значит предыдущий запрос завершился
      //или это первый запуск. В любом случае, надо сбросить обработчик таймаута
      clearTimeoutHandler();
      //При изменении статуса запроса вызвать эту функцию
      xhr.onreadystatechange = local_getInfo;

      xhr.onerror = function(error) {
	console.log(error);
	console.log(hObj.name+" xhr.readyState="+xhr.readyState+" xhr.status="+xhr.status);
	//handleError();
	clearTimeoutHandler();
	finished = true;
	}

      //Запрос

      //При первом запуске получим i=0
      i++;
      //Есть ещё параметры или нет?
      if (i >= hObj.parm.length) {
	clearTimeoutHandler();
	set_active_default();
	on_selSites_change();
	return;
      }
      //Таймаут по умолчанию
      aSleep = sleep_timeout;
      //Поддерживает ли этот параметр автоопределение?
      if (hObj.parm[i].detect.auto == "true") {
	//Работаем
	finished = false;
	console.log ("Автоопределяем "+hObj.name+" параметр "+hObj.parm[i].name);
	//Установка обработчика таймаута
	setTimeoutHandler(requestTimeout);
	//Некое подобие кэширования на стороне клиента
	//Если мы ещё не опрашивали УРЛ, запустить запрос
	if (tURL != unescape(hObj.parm[i].detect.url)  || xhr.readyState != 4) {
	  tURL = unescape(hObj.parm[i].detect.url);
	  iObj = hObj.parm[i].detect;
	  xhr.open("GET", tURL, true);
	  xhr.send(null);
	} else {
	  //... иначе воспользоваться предыдущими результатами
	  iObj = hObj.parm[i].detect;
	  local_getInfo();
	  //Т.к. данные уже готовы, нет смысла ждать долго
	  aSleep = short_sleep;
	}
      }
    } catch(e) {
      console.error("exception: " + e);
      //handleError();
      document.getElementById("verify_options").innerHTML = "Случилась непредвиденная ошибка. Попробуйте ещё раз. Если не получится, обратитесь, пожалуйста, к разработчику.";
    }

  //Запрос асинхронный, так что можно немного отдохнуть
  window.setTimeout(local_sleep, aSleep);
  }

  document.getElementById("verify_options").innerHTML = "Запускаю автоопределение, подождите...<br />";
  //Запуск цикла опроса параметров
  window.setTimeout(local_sleep, 0);
}

//Функция сохраняет параметры
function save_options() {
  //Сохраняем в текстовом виде
  localStorage["objSites.host"] = JSON.stringify(objSites.host);
  //Посылаем извещение основной части расширения о том, что опции изменились
  chrome.extension.sendRequest({content:"reread_options"});
  restore_options();
  document.getElementById("verify_options").innerHTML = "Настройки сохранены";
}

//Функция проверки параметров
function verify_options() {
  document.getElementById("verify_options").innerHTML = "Опрашиваю трекеры, потерпите немного...";
  //Посылаем извещение основной части расширения о том, что мы хотим опросить трекеры,
  //содержащиеся в нашем местном объекте objSites
  chrome.extension.sendRequest({content:"verify", objSites: objSites}, function (response) {
    //Функция ответа
    //Подготовить HTML
    document.getElementById("verify_options").innerHTML = response.content.replace(/\n/igm,"<br \>");
    console.log(response.content);
  });
}

//Функция сброса настроек текущего хоста на натсройки по умолчанию
function reset_host() {
  var t;
  var i = document.getElementById("selSites").value;
  if (!i)
    return;
  var n = objSites.host[i].name;

  //Найти шаблон с таким же именем
  //см. utils.js
  t = findHostByName(n, objSitesTemplate)
  if (t) {
    document.getElementById("xmltext").value = dumpHost(t);
    on_xmltext_change();
  }
}

//Удалить всё!
function delete_all() {
  objSites.host = [];
  restore_options();
}

function set_inactive_all() {
  document.getElementById("selSitesTemplate").disabled = true;
  document.getElementById("selSites").disabled = true;
  document.getElementById("xmltext").disabled = true;
  document.getElementById("detect").disabled = true;
  document.getElementById("verify").disabled = true;
  document.getElementById("resethost").disabled = true;
  document.getElementById("deleteall").disabled = true;
  document.getElementById("reload").disabled = true;
  document.getElementById("save").disabled = true;
}

function set_active_default () {
  document.getElementById("selSitesTemplate").disabled = false;
  document.getElementById("selSites").disabled = false;
  document.getElementById("xmltext").disabled = false;
  document.getElementById("detect").disabled = true;
  document.getElementById("verify").disabled = false;
  document.getElementById("resethost").disabled = true;
  document.getElementById("deleteall").disabled = false;
  document.getElementById("reload").disabled = false;
  document.getElementById("save").disabled = false;
}

function advancedMode_toggle() {
  if (document.getElementById("advancedMode").checked) {
    document.getElementById("td_xmltext").className = "";
    document.getElementById("td_detect").className = "";
    document.getElementById("resethost").className = "";
  } else {
    document.getElementById("td_xmltext").className = "hidden";
    document.getElementById("td_detect").className = "hidden";
    document.getElementById("resethost").className = "hidden";
  }
}

document.addEventListener("DOMContentLoaded", function() {
  console.log("Ура! Запуск!");
  //Устанавливаем обработчики
  document.getElementById("selSitesTemplate").onchange = on_selSitesTemplate_change;
  document.getElementById("advancedMode").onclick = advancedMode_toggle;
  document.getElementById("selSites").onchange = on_selSites_change;
  document.getElementById("selSites").ondblclick = on_selSites_dblclick;
  document.getElementById("xmltext").onchange = on_xmltext_change;
  document.getElementById("detect").onclick = autodetect_host;
  document.getElementById("verify").onclick = verify_options;
  document.getElementById("resethost").onclick = reset_host;
  document.getElementById("deleteall").onclick = delete_all;
  document.getElementById("reload").onclick = init;
  document.getElementById("save").onclick = save_options;
  init();
});